package com.lazerycode.jmeter.mojo; import com.lazerycode.jmeter.configuration.JMeterArgumentsArray; import com.lazerycode.jmeter.configuration.JMeterProcessJVMSettings; import com.lazerycode.jmeter.configuration.ProxyConfiguration; import com.lazerycode.jmeter.configuration.RemoteConfiguration; import com.lazerycode.jmeter.exceptions.IOException; import com.lazerycode.jmeter.properties.ConfigurationFiles; import com.lazerycode.jmeter.properties.PropertiesMapping; import org.apache.commons.io.FileUtils; import org.apache.maven.execution.MavenSession; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecution; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.settings.Proxy; import org.apache.maven.settings.Settings; import org.joda.time.format.DateTimeFormat; import java.io.File; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import static com.lazerycode.jmeter.utility.UtilityFunctions.isSet; /** * JMeter Maven plugin. * This is a base class for the JMeter mojos. * * @author Tim McCune */ @SuppressWarnings({"UnusedDeclaration", "FieldCanBeLocal", "JavaDoc"}) // Mojos get their fields set via reflection public abstract class AbstractJMeterMojo extends AbstractMojo { /** * Sets the list of include patterns to use in directory scan for JMX files. * Relative to testFilesDirectory. */ @Parameter protected List<String> testFilesIncluded = new ArrayList<>(); /** * Sets the list of exclude patterns to use in directory scan for JMX files. * Relative to testFilesDirectory. */ @Parameter protected List<String> testFilesExcluded = new ArrayList<>(); /** * Path under which .conf files are stored. */ @Parameter(defaultValue = "${basedir}/src/test/conf") protected File confFilesDirectory; /** * Path under which JMX files are stored. */ @Parameter(defaultValue = "${basedir}/src/test/jmeter") protected File testFilesDirectory; /** * Timestamp the test results. */ @Parameter(defaultValue = "true") protected boolean testResultsTimestamp; /** * Append the results timestamp to the filename * (It will be prepended by default if testResultsTimestamp is set to true) */ @Parameter(defaultValue = "false") protected boolean appendResultsTimestamp; /** * Set the format of the timestamp that is appended to the results filename. * (This assumes that testResultsTimestamp is set to 'true') * For formatting see http://joda-time.sourceforge.net/apidocs/org/joda/time/format/DateTimeFormat.html */ @Parameter() protected String resultsFileNameDateFormat; /** * Set the directory that JMeter results are saved to. */ @Parameter(defaultValue = "${project.build.directory}/jmeter/results") protected File resultsDirectory; /** * Generate Jmeter Reports (this will force your .jtl's into .csv mmode) */ @Parameter(defaultValue = "false") protected boolean generateReports; /** * Set the directory that JMeter reports are saved to. */ @Parameter(defaultValue = "${project.build.directory}/jmeter/reports") protected File reportDirectory; /** * Set the directory that JMeter test files are copied into as part of the build. */ @Parameter(defaultValue = "${project.build.directory}/jmeter/testFiles") protected File testFilesBuildDirectory; /** * Set the directory that JMeter logs are saved to. */ @Parameter(defaultValue = "${project.build.directory}/jmeter/logs") protected File logsDirectory; /** * Absolute path to JMeter custom (test dependent) properties file. */ @Parameter protected List<File> customPropertiesFiles = new ArrayList<>(); /** * Use maven proxy configuration if no specific proxy configuration provided */ @Parameter protected boolean useMavenProxy; /** * Maven settings */ @Parameter(defaultValue = "${settings}", readonly = true) protected Settings settings; /** * Value class that wraps all proxy configurations. */ @Parameter protected ProxyConfiguration proxyConfig; /** * Value class that wraps all remote configurations. */ @Parameter protected RemoteConfiguration remoteConfig; /** * Value class that wraps all JMeter Process JVM settings. */ @Parameter protected JMeterProcessJVMSettings jMeterProcessJVMSettings; /** * Set a root log level to override all log levels used by JMeter * Valid log levels are: ERROR, WARN, INFO, DEBUG (They are not case sensitive); * If you try to set an invalid log level it will be ignored */ @Parameter protected String overrideRootLogLevel; /** * Suppress JMeter output */ @Parameter(defaultValue = "false") protected boolean suppressJMeterOutput; /** * The information extracted from the Mojo being currently executed */ @Parameter(defaultValue = "${mojoExecution}", required = true, readonly = true) protected MojoExecution mojoExecution; @Parameter(defaultValue = "${session}", readonly = true) private MavenSession session; /** * Skip the JMeter tests */ @Parameter(defaultValue = "${skipTests}") protected boolean skipTests; /** * Set a pause in seconds after each test that is run. */ @Parameter(defaultValue = "0") protected String postTestPauseInSeconds; /** * The filename used to store the results config */ @Parameter(defaultValue = "${project.build.directory}/config.json") protected String testConfigFile; //------------------------------------------------------------------------------------------------------------------ /** * Place where the JMeter files will be generated. */ @Parameter(defaultValue = "${project.build.directory}/jmeter") protected transient File jmeterDirectory; /** * The project build directory */ @Parameter(defaultValue = "${project.build.directory}") transient File projectBuildDirectory; protected static String runtimeJarName; protected static JMeterArgumentsArray testArgs; protected static File workingDirectory; protected static Map<ConfigurationFiles, PropertiesMapping> propertiesMap = new HashMap<>(); //================================================================================================================== @Override public final void execute() throws MojoExecutionException, MojoFailureException { if (skipTests) { if (session.getGoals().contains("jmeter:gui")) { if (!mojoExecution.getExecutionId().equals("default-cli") && !mojoExecution.getLifecyclePhase().equals("compile")) { getLog().info("Performance tests are skipped."); return; } } else { getLog().info("Performance tests are skipped."); return; } } // load maven proxy if needed if (useMavenProxy && proxyConfig == null) { loadMavenProxy(); } doExecute(); } protected abstract void doExecute() throws MojoExecutionException, MojoFailureException; /** * Generate the initial JMeter Arguments array that is used to create the command line that we pass to JMeter. * * @throws MojoExecutionException */ protected void initialiseJMeterArgumentsArray(boolean disableGUI, boolean isCSVFormat) throws MojoExecutionException { testArgs = new JMeterArgumentsArray(disableGUI, jmeterDirectory.getAbsolutePath()); testArgs.setResultsDirectory(resultsDirectory.getAbsolutePath()); testArgs.setResultFileOutputFormatIsCSV(isCSVFormat); if (generateReports) { testArgs.setReportsDirectory(reportDirectory.getAbsolutePath()); } if (testResultsTimestamp) { testArgs.setResultsTimestamp(true); testArgs.appendTimestamp(appendResultsTimestamp); if (isSet(resultsFileNameDateFormat)) { try { testArgs.setResultsFileNameDateFormat(DateTimeFormat.forPattern(resultsFileNameDateFormat)); } catch (Exception ex) { getLog().error("'" + resultsFileNameDateFormat + "' is an invalid DateTimeFormat. Defaulting to Standard ISO_8601."); } } } testArgs.setProxyConfig(proxyConfig); for (File customPropertiesFile : customPropertiesFiles) { testArgs.setACustomPropertiesFile(customPropertiesFile); } testArgs.setLogRootOverride(overrideRootLogLevel); testArgs.setLogsDirectory(logsDirectory.getAbsolutePath()); } /** * Try to load the active maven proxy. */ protected void loadMavenProxy() { if (settings == null) return; try { Proxy mvnProxy = settings.getActiveProxy(); if (mvnProxy != null) { ProxyConfiguration newProxyConf = new ProxyConfiguration(); newProxyConf.setHost(mvnProxy.getHost()); newProxyConf.setPort(mvnProxy.getPort()); newProxyConf.setUsername(mvnProxy.getUsername()); newProxyConf.setPassword(mvnProxy.getPassword()); newProxyConf.setHostExclusions(mvnProxy.getNonProxyHosts()); proxyConfig = newProxyConf; getLog().info("Maven proxy loaded successfully"); } else { getLog().warn("No maven proxy found, but useMavenProxy set to true."); } } catch (Exception e) { getLog().error("Error while loading maven proxy", e); } } static void CopyFilesInTestDirectory(File sourceDirectory, File destinationDirectory) throws IOException { try { FileUtils.copyDirectory(sourceDirectory, destinationDirectory); } catch (java.io.IOException e) { throw new IOException(e.getMessage(), e); } } }